from scapy.all import *
import time

def handle_icmp(packet):
    # 只处理 ICMP Timestamp Request 报文（类型 13）
    if ICMP in packet and packet[ICMP].type == 13:
        print(f"收到来自 {packet[IP].src} 的时间请求")
        
        # 构建应答报文（ICMP Timestamp Reply，类型 14）
        reply = IP(dst=packet[IP].src)/ICMP(type=14, id=packet[ICMP].id, seq=packet[ICMP].seq)/\
                Raw(load=packet[Raw].load)  # 复用请求中的原始负载（含客户端发送时间）
        
        # 填充服务器时间戳（单位：毫秒，ICMP 时间戳为 32 位无符号整数，以毫秒为单位）
        # 时间戳格式：[原始发送时间戳, 服务器接收时间戳, 服务器发送时间戳]
        send_ts = struct.unpack("!III", packet[Raw].load)[0]  # 客户端发送时间
        recv_ts = int(time.time() * 1000) & 0xFFFFFFFF  # 服务器接收时间（取低 32 位）
        trans_ts = int(time.time() * 1000) & 0xFFFFFFFF  # 服务器发送时间
        reply[Raw].load = struct.pack("!III", send_ts, recv_ts, trans_ts)
        
        # 发送应答
        send(reply, verbose=0)
        print(f"已向 {packet[IP].src} 回复时间戳")

if __name__ == "__main__":
    print("ICMP 时间服务器启动，监听端口...")
    # 监听所有 ICMP 报文（需要 root 权限）
    sniff(prn=handle_icmp, filter="icmp", store=0)